﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZXing.QrCode.Internal;

namespace QrGenerator
{
    public static class QrGenerator
    {
        public static void Print(byte[][] mat)
        {
            for (int i = 0; i < mat.Length; i++)
            {
                for (int j = 0; j < mat[i].Length; j++)
                {
                    Console.Write(mat[i][j] == 0 ? " " : "#");
                }
                Console.WriteLine();
            }
        }

        public static void GenerateAndDraw(string text)
        {
            QRCode q = GetQrCode(text);


            //var qr = writer.Encode(text);//writer.encode(text, BarcodeFormat.QR_CODE, 10, 10);
            Console.WriteLine("found " + q.Version.DimensionForVersion);

            Print(q.Matrix.Array);


        }

        public static QRCode GetQrCode(string text)
        {
            QRCode q = ZXing.QrCode.Internal.Encoder.encode(text, ErrorCorrectionLevel.H);

            if (q.Version != ZXing.QrCode.Internal.Version.getVersionForNumber(1) || q.Mode != Mode.NUMERIC)
            {
                Console.WriteLine("greater version or non numeric");
                throw new Exception("greater version or non numeric");

            }
            return q;
        }

        static int Distance(byte[] a, byte[] b)
        {
            int error = 0;
            for (int i = 0; i < a.Length; i++)
            {
                if (a[i] != b[i])
                    error++;
            }
            return error;
        }

        public static byte[] ToArray(this byte[][] mat)
        {
            int c = 0;
            var res = new byte[mat.Length * mat.Length];
            for (int i = 0; i < mat.Length; i++)
            {
                for (int j = 0; j < mat.Length; j++)
                {
                    res[c++] = mat[i][j];
                }
            }
            return res;
        }

        public static Tuple<long, byte[]>[] CreateRandomDataSet(int count, long max, int seed = -1)
        {
            var rand = seed == -1 ? new Random() : new Random(seed);
            var res = new Tuple<long, byte[]>[count];

            for (int i = 0; i < count; i++)
            {
                //var num = (long)(((double)rand.Next() / (double)int.MaxValue) * 100000000000000000.0);
                var num = (long)(rand.NextDouble() * max);
                var qr = GetQrCode(num.ToString());
                res[i] = new Tuple<long, byte[]>(num, qr.Matrix.Array.ToArray());
            }

            return res;
        }

        public static Tuple<long, byte[]>[] CreateDataSet(int count, long max, int seed = -1)
        {
            var rand = seed == -1 ? new Random() : new Random(seed);
            var res = new Tuple<long, byte[]>[count];

            for (int i = 0; i < count; i++)
            {
                //var num = (long)(((double)rand.Next() / (double)int.MaxValue) * 100000000000000000.0);
                var num = i;
                var qr = GetQrCode(num.ToString());
                res[i] = new Tuple<long, byte[]>(num, qr.Matrix.Array.ToArray());
            }

            return res;
        }

        // versione 1 con error recover al max e' 10 caratteri a disegno
        //static void Main(string[] args)
        //{
        //    bool looping = true;

        //    Console.ForegroundColor = ConsoleColor.Black;
        //    Console.BackgroundColor = ConsoleColor.White;

        //    var dataset = CreateDataSet(1000, 0);

        //    var q_1 = GetQrCode("2").Matrix.Array.ToArray();
        //    for (int i = 0; i < 100; i++)
        //    {

        //        var q_2 = GetQrCode(i.ToString()).Matrix.Array.ToArray();
        //        Console.WriteLine("distance = " + Distance(q_1, q_2));
        //    }

        //    while (looping)
        //    {
        //        var text = Console.ReadLine();
        //        looping = text != "exit";
        //        GenerateAndDraw(text);
        //    }

        //    //for (int i = 0; i < 256; i++)
        //    //{
        //    //    Console.WriteLine(i + " -> " + (char) i);
        //    //}


        //    //Console.ReadKey();
        //}
    }
}
